﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using PlanB.ShareDove.ConferenceOrganization.ServiceLayer.ServiceFacade.Entities;
using PlanB.Core.Configuration;
using PlanB.ShareDove.ConferenceOrganization.BusinessLayer;
using PlanB.ShareDove.ConferenceOrganization.BusinessLayer.DataLayerInterface.Entities;
using PlanB.ShareDove.ConferenceOrganization.ServiceLayer.ServiceFacade.Transformations;
using System.ServiceModel;

namespace PlanB.ShareDove.ConferenceOrganization.ServiceLayer.ServiceFacade
{
    //TODO: remove the references to the data layer implementations when finished with the testing - they are here just to enable us debugging (stepping into those assemblies). In the reality, the dependencies to these assemblies are injected.

    /// <summary>
    /// A class which is used as a kind of interdace (facade) between service calls and business logic.
    /// Since we want to pass  as little as possiblle of data, but as much as possivble of information through the service
    /// We will make a "lite" version of all entities, which "flatten" the data, even if it means making it redundant, for pushing int
    /// through service.
    /// 
    /// As well, a facade will be put arround the buiness logic methods, to expose exactly those methods to the outer world which are really needed.
    /// </summary>
    public class ServiceFacade
    {

        private object dataContext;

        private string dataLayerImplementation;
        private string dataLayerClass;
        private string siteName;
        private string webName;

        #region Public Properties

        public string DataLayerImplementation
        {
            set
            {
                this.dataLayerImplementation = value;
            }
            get
            {
                return this.dataLayerImplementation;
            }


        }

        public string DataLayerClass
        {
            set
            {
                this.dataLayerClass = value;
            }
            get
            {
                return this.dataLayerClass;
            }
        }

        public string SiteName
        {
            set
            {
                this.siteName = value;
            }
            get
            {
                return this.siteName;
            }
        }

        public string WebName
        {
            set
            {
                this.webName = value;
            }
            get
            {
                return this.webName;
            }
        }

        public object DataContext
        {
            set
            {
                this.dataContext = value;
            }
            get
            {
                return this.dataContext;
            }
        }

        #endregion

        #region Public Methods
        /// <summary>
        /// Returns some dummy data for service testing
        /// </summary>
        /// <returns></returns>
        public List<string> GetSomeDummyData()
        {
            List<string> lst = new List<string>();
            for (int i = 0; i < 10; i++)
            {
                lst.Add(string.Format("Item number {0}", i + 1));
            }

            return lst;
        }
        #endregion

        /// <summary>
        /// Gets a conference agenda for a specified day
        /// </summary>
        /// <param name="day">A day for which we want to retrieve the conference agenda</param>
        /// <returns>List of the sessions for the day</returns>
        public List<ConferenceSessionLite> GetAgendaForDay(DateTime day)
        {
            try
            {
                if (string.IsNullOrEmpty(this.siteName))
                {
                    this.siteName = ConfigurationManager.AppSettings["spsite"];
                }

                if (string.IsNullOrEmpty(this.webName))
                {
                    this.webName = ConfigurationManager.AppSettings["spweb"];
                }

                if (string.IsNullOrEmpty(this.dataLayerImplementation))
                {
                    this.dataLayerImplementation = ConfigurationManager.AppSettings["datalayerimplementation"];
                }

                if (string.IsNullOrEmpty(this.dataLayerClass))
                {
                    this.dataLayerClass = ConfigurationManager.AppSettings["datalayerclass"];
                }

                List<ConferenceSessionLite> sessions = new List<ConferenceSessionLite>();

                ConfigurationInformation configuration = new ConfigurationInformation()
                {
                    DataLayerImplementationAssembly = this.dataLayerImplementation,
                    DataLayerImplementationClassName = this.dataLayerClass
                };

                ConferenceOrganizationBusinessProcesses target = new ConferenceOrganizationBusinessProcesses(configuration);

                IEnumerable<ConferenceSession> conferenceSessions;

                if (this.dataContext == null)
                {
                    this.dataContext = string.Format("{0};{1}", this.siteName, this.webName);
                }
                
                
                conferenceSessions = target.GetSessionsForDay(this.dataContext, day);

                if (conferenceSessions != null)
                {
                    foreach (ConferenceSession confSession in conferenceSessions)
                    {
                        sessions.Add(EntityTransformers.TransformSessionToLite(confSession));
                    }
                }

                return sessions;
            }
            catch (Exception ex)
            {
                throw new FaultException(
                new FaultReason(ex.Message),
                new FaultCode("Error retrieving agenda for day")
                );
            }
        }
    }
}
